#pragma once
#include <memory>
#include <sys/epoll.h>
#include "socket.hpp"
#include "connection.hpp"
#include "reactor.hpp"
#include "IOserverce.hpp"

class Listener
{
public:
    Listener(uint16_t port, IOserverce& io)
        : _port(port), _listensock(std::make_unique<net::TcpSocket>(port)), _io(io)
    {
        InetAddr addr("0", port);
        _listensock->BuildServerSocket(addr);
    }

    ~Listener()
    {
        _listensock->Close();
    }

    int SockFd()
    {
        return _listensock->SockFd();
    }

    void Accepter(Connection *conn)
    {
        while (true) // 可能一次有多个连接
        {
            InetAddr addr;
            int errcode;
            int socKfd = _listensock->Accept(&addr, &errcode);
            if (socKfd < 0) // 出错
            {
                if (errcode == EWOULDBLOCK || errcode == EAGAIN) // 已经把底层的新连接全部获取完了
                {
                    Log(DEBUG, "accepter all link");
                    break;
                }
                else if (errcode == EINTR) // 被信号中断了
                {
                    Log(DEBUG, "accepter interupt by signal");
                    continue;
                }
                else
                {
                    Log(WARNING, "%s", strerror(errcode));
                    break;
                }
            }
            else
            {
                // 添加新连接 在Listener中将新连接放到Reactor中
                // conn->_self->AddConnection(socKfd,EPOLLIN|EPOLLET,std::bind(&IOserverce::HandlerRecv,&io,std::placeholders::_1),IOserverce::HandlerSend,IOserverce::HandlerExcept);
                conn->_self->AddConnection(socKfd,
                                           EPOLLIN | EPOLLET,
                                           std::bind(&IOserverce::HandlerRecv, &_io, std::placeholders::_1),
                                           std::bind(&IOserverce::HandlerSend, &_io, std::placeholders::_1),
                                           std::bind(&IOserverce::HandlerExcept, &_io, std::placeholders::_1));
            }
        }
    }

private:
    uint16_t _port;
    std::unique_ptr<net::Socket> _listensock;
    IOserverce &_io;
};